using System;

namespace Dida
{
	/// <summary>
	/// A transformation that's build up from (multiple) rotations and translations, 
	/// but no scaling or sheering or other kinds of transformations.
	/// </summary>
	public struct SimpleTransform
	{
		/// <summary>
		/// The position, ie. the translation part of this transform. 
		/// </summary>
		public Vector3D pos;
		/// <summary>
		/// The rotation part of this transform.
		/// </summary>
		/// <remarks>
		/// This rotation is applied with <see cref = "pos"/> as it's pivot.
		/// </remarks>
		public Quaternion rot;

		/// <summary>
		/// Creates a new transform, from the given parameters.
		/// </summary>
		/// <param name="pos">The initial position.</param>
		/// <param name="rot">The initial rotation.</param>
		public SimpleTransform(Vector3D pos, Quaternion rot)
		{
			this.pos = pos;
			this.rot = rot;
		}

		/// <summary>
		/// Combines the two transforms. This function is the analogue of mulitplying a matrix.
		/// </summary>
		/// <remarks>
		/// After this method has been called, applying the transform has the effect of
		/// first applying the original transform, and then applying the transform 
		/// in <paramref name="b"/>.
		/// </remarks>
		/// <param name="b">The transform you want to combine this transform with.</param>
		public void Combine(SimpleTransform b)
		{
			b.rot.RotateVector(ref pos);
			pos += b.pos;

			rot *= b.rot;
		}

		public Matrix4 ToMatrix()
		{
			return rot.ToMatrix() * Matrix4.GetTranslationMatrix(pos);
		}

		/// <summary>
		/// Applies this trnasform to the given vector.
		/// </summary>
		/// <param name="pt">The input vector, you want to transform</param>
		/// <returns>The transformed vector.</returns>
		public Vector3D TransformPoint(Vector3D pt)
		{
			Vector3D ret = pt;
			rot.RotateVector(ref ret);
			ret += pos;
			return ret;
		}
	}
}
